#pragma comment(lib, "glew32.lib")
#pragma comment(lib, "freeglut.lib")
#pragma comment(lib, "soil.lib")

#include <stdio.h>
#include <gl/glew.h>
#include <gl/glut.h>
#include <gl/soil.h>
#include <gl/freeglut_ext.h>
#include <iostream>

int windowWidth = 0;
int windowHeight = 0;

// constants
const int   SCREEN_WIDTH = 400;
const int   SCREEN_HEIGHT = 300;
const float CAMERA_DISTANCE = 6.0f;
const int   TEXT_WIDTH = 8;
const int   TEXT_HEIGHT = 13;
const int   TEXTURE_WIDTH = 256;  // NOTE: texture size cannot be larger than
const int   TEXTURE_HEIGHT = 256;  // the rendering window size in non-FBO mode

GLuint fboId;
GLuint textureId;
GLuint rboId;


void draw()
{
	glBindTexture(GL_TEXTURE_2D, textureId);

	glColor4f(1, 1, 1, 1);
	glBegin(GL_TRIANGLES);
	// front faces
	glNormal3f(0, 0, 1);
	// face v0-v1-v2
	glTexCoord2f(1, 1);  glVertex3f(1, 1, 1);
	glTexCoord2f(0, 1);  glVertex3f(-1, 1, 1);
	glTexCoord2f(0, 0);  glVertex3f(-1, -1, 1);
	// face v2-v3-v0
	glTexCoord2f(0, 0);  glVertex3f(-1, -1, 1);
	glTexCoord2f(1, 0);  glVertex3f(1, -1, 1);
	glTexCoord2f(1, 1);  glVertex3f(1, 1, 1);

	// right faces
	glNormal3f(1, 0, 0);
	// face v0-v3-v4
	glTexCoord2f(0, 1);  glVertex3f(1, 1, 1);
	glTexCoord2f(0, 0);  glVertex3f(1, -1, 1);
	glTexCoord2f(1, 0);  glVertex3f(1, -1, -1);
	// face v4-v5-v0
	glTexCoord2f(1, 0);  glVertex3f(1, -1, -1);
	glTexCoord2f(1, 1);  glVertex3f(1, 1, -1);
	glTexCoord2f(0, 1);  glVertex3f(1, 1, 1);

	// top faces
	glNormal3f(0, 1, 0);
	// face v0-v5-v6
	glTexCoord2f(1, 0);  glVertex3f(1, 1, 1);
	glTexCoord2f(1, 1);  glVertex3f(1, 1, -1);
	glTexCoord2f(0, 1);  glVertex3f(-1, 1, -1);
	// face v6-v1-v0
	glTexCoord2f(0, 1);  glVertex3f(-1, 1, -1);
	glTexCoord2f(0, 0);  glVertex3f(-1, 1, 1);
	glTexCoord2f(1, 0);  glVertex3f(1, 1, 1);

	// left faces
	glNormal3f(-1, 0, 0);
	// face  v1-v6-v7
	glTexCoord2f(1, 1);  glVertex3f(-1, 1, 1);
	glTexCoord2f(0, 1);  glVertex3f(-1, 1, -1);
	glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
	// face v7-v2-v1
	glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
	glTexCoord2f(1, 0);  glVertex3f(-1, -1, 1);
	glTexCoord2f(1, 1);  glVertex3f(-1, 1, 1);

	// bottom faces
	glNormal3f(0, -1, 0);
	// face v7-v4-v3
	glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);
	glTexCoord2f(1, 0);  glVertex3f(1, -1, -1);
	glTexCoord2f(1, 1);  glVertex3f(1, -1, 1);
	// face v3-v2-v7
	glTexCoord2f(1, 1);  glVertex3f(1, -1, 1);
	glTexCoord2f(0, 1);  glVertex3f(-1, -1, 1);
	glTexCoord2f(0, 0);  glVertex3f(-1, -1, -1);

	// back faces
	glNormal3f(0, 0, -1);
	// face v4-v7-v6
	glTexCoord2f(0, 0);  glVertex3f(1, -1, -1);
	glTexCoord2f(1, 0);  glVertex3f(-1, -1, -1);
	glTexCoord2f(1, 1);  glVertex3f(-1, 1, -1);
	// face v6-v5-v4
	glTexCoord2f(1, 1);  glVertex3f(-1, 1, -1);
	glTexCoord2f(0, 1);  glVertex3f(1, 1, -1);
	glTexCoord2f(0, 0);  glVertex3f(1, -1, -1);
	glEnd();
	glBindTexture(GL_TEXTURE_2D, 0);
}





void ChangeSize(int w, int h)
{
	windowWidth = w;
	windowHeight = h;

	if (h == 0)
		h = 1;
	glViewport(0, 0, w, h);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0, w*1.0 / h, 0.01, 1000.0f);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void SetupRC()
{

	glGenTextures(1, &textureId);
	glBindTexture(GL_TEXTURE_2D, textureId);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
		GL_RGBA, GL_UNSIGNED_BYTE, 0);
	glBindTexture(GL_TEXTURE_2D, 0);


	glGenFramebuffers(1, &fboId);
	glBindFramebuffer(GL_FRAMEBUFFER, fboId);
	glGenRenderbuffers(1, &rboId);
	glBindRenderbuffer(GL_RENDERBUFFER, rboId);
	glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, TEXTURE_WIDTH, TEXTURE_HEIGHT);
	glBindRenderbuffer(GL_RENDERBUFFER, 0);

	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureId, 0);
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboId);

	glBindFramebuffer(GL_FRAMEBUFFER, 0);

	glEnable(GL_TEXTURE_2D);
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void RenderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

	glLoadIdentity();
	glTranslated(0, 0, -20);


	glBindFramebuffer(GL_FRAMEBUFFER, fboId);
	glPushMatrix();
	glRotatef(angle*0.5f, 1, 0, 0);
	glRotatef(angle, 0, 1, 0);
	glRotatef(angle*0.7f, 0, 0, 1);
	glTranslatef(0, -1.575f, 0);
	drawTeapot();
	glPopMatrix();
	glBindFramebuffer(GL_FRAMEBUFFER, 0);




	glutSwapBuffers();
}



int main(int argc, char* argv[])
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_STENCIL);
	glutInitWindowSize(800, 600);
	glutCreateWindow("OpenGL");
	glutReshapeFunc(ChangeSize);
	glutDisplayFunc(RenderScene);

	GLenum err = glewInit();
	if (GLEW_OK != err) {
		fprintf(stderr, "GLEW Error: %s\n", glewGetErrorString(err));
		return 1;
	}

	SetupRC();

	glutMainLoop();
	return 0;
}